class: inverse,left, middle background-image: url(data:image/png;base64,#background.png) background-size: cover <img src="data:image/png;base64,#LOGO_DIPLOMADO.png" width="500px"/> ## Módulo 3: Análisis masivo de datos satelitales y Google Earth Engine ### Introducción a las Series de tiempo Matías Olea <br> <a href="https://orcid.org/0000-0003-0194-7784"> ORCID </a><br> matias.olea@pucv.cl</a><br> .large[<b><a href="https://www.pucv.cl/uuaa/site/edic/base/port/labgrs.html">LabGRS</a> | Noviembre 2025</b>] <br> --- class: center,middle background-image: url(data:image/png;base64,#labgrs_logo.png) background-size: 35% --- ## Contenidos .pull-left[ 1) Que es una serie de tiempo. 2) Rellenado de datos. 3) Remuestreo temporal. 4) Componentes de una serie y descomposición. 6) Anomalías respecto a desviaciones de la media (Z-score). ] .pull-right[ <img src="data:image/png;base64,#https://raw.githubusercontent.com/allisonhorst/stats-illustrations/main/rstats-artwork/r_rollercoaster.png" width="650px"/> ] --- ### Series de tiempo Una **serie de tiempo** corresponde a un conjunto de observaciones de variables cuantitativas en el tiempo. Estas variables pueden o no tener distintos comportamiento en el tiempo.
--- ### Series de tiempo Las series las podemos encontrar como estacionarias y no estacionarias .pull-left[ **Estacionaria**. Es aquella cuya media y varianza se mantienen en el tiempo, es decir, son constantes, por lo que facilita más su modelamiento.
] .pull-right[ **No Estacionaria**. Es aquella cuya media y varianza cambian en el tiempo, es decir, no son constantes, por lo que dificulta más su modelamiento.
] --- ### Series de tiempo Las series temporales poseen 4 componentes (3 para algunos autores) los cuales son en simples palabras: -- **Tendencia** (T - trend): corresponde al comportamiento de la media y la varianza en el tiempo. -- **Ciclos** (C - cycle): oscilaciones respecto a la tendencia en largas o medias escalas temporales. Como se desprende de la tendencia, algunos autores no la consideran como un componente propiamente tal. -- **Estacionalidad** (S - seasonality): comportamientos determinados en periodos fijos. Corresponden a cambios dentro de unidades de tiempo de manera regular (como cambios intra-anuales). -- **Aleatorio** (R - random): comportamiento sin un patrón determinado. Es un comportamiento practicamente impredecible. Lo podemos encontrar en la literatura también como "erratico". --- ### Series de tiempo <center><img src="data:image/png;base64,#raster_ts.jpg" width="1000px"/></center> --- ### Series de tiempo #### Lectura de datos ``` r library(tidyverse) library(readxl) ``` ``` ## [1] "character" ``` ``` r setwd("C:/TuDirectorio/") EVI <- read_excel("Tabla_Serie_EVI.xlsx") class(EVI$Fecha) # consultamos la clase EVI$Fecha <- as.Date(EVI$Fecha) # transformamos a formato de fechas ``` --- ### Series de tiempo <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-7-1.png" width="100%" /> --- ### Series de tiempo #### Rellenado de la serie Existen muchos paquetes que nos permiten realizar rellenos o suavizado de nuestros datos como **gapfill**, **oce**, **imputeTS**, **TSstudio**, o **phenofit**, entre otros. Los más frecuentes para análisis de datos de IV (Índice de Vegetación) proveniente de datos satelitales es **phenopix** o el software **TIMESAT**. Otra opción es la creación de Composiciones (Composites), que realizan agregaciones temporales en ciertos intervalos de tiempo para asegurar una mayor cantidad de datos disponible. Un claro de ejemplo de esto es el producto MOD13Q1 de Modis que realiza composites de 16-días. Para este ejercicio ocuparemos el paquete imputeTS. ``` r library("imputeTS") ``` --- ### Series de tiempo #### Rellenado de datos Para las funciones de imputeTS, necesitamos un objeto clase Time-Series: ``` r ts_plant <- ts(EVI$EVI_Plantacion_gap, EVI$Fecha) ``` ``` r EVI$Lin <- na_interpolation(x=ts_plant, # nuestro objeto TS option = "linear", # metodo de rellenado maxgap = Inf) %>% # n de NA consecutivos para rellenar as.numeric() # resultado a vector numerico para incluirlo en la tabla ``` --- ### Series de tiempo #### Remuestreo temporal El remuestreo temporal consiste en realizar **agregaciones** o **agrupaciones** temporales, según una condición de tiempo (mensual, anual, semestral, trimestral, etc.). Comunmente, estos ejercicios se realizan para: - Tener una **periodicidad** o **intérvalos de tiempo regulares** en nuestros datos. Ej: Caso Landsat (16-días 1 satelite / 8-días 2 satelites) - **Disminuir las brechas** por pérdida de datos causados por la presencia de nubes. Ej: Composites de MODIS. De datos diarios a cada 16-dias. - Homologar fuentes de información con **diferentes resoluciones temporales**. Ej: Datos de dendrocronológicos (1-año) con datos satelitales o climáticos. --- class: center,middle background-image: url(data:image/png;base64,#tiempo.png) background-size: 90% background-color: black --- ### Series de tiempo #### Remuestreo temporal Para este ejemplo, utilizaremos nuestra serie de tiempo EVI de MODIS-Aqua de 16-días (23 datos al año) para remuestrearla temporalmene en datos mensuales. **Opción 1: usando tidyverse** ``` r EVI$month <- month(EVI$Fecha) # creamos una nueva columna con los meses EVI$year <- year(EVI$Fecha) # creamos una nueva columna con los años tabla_mensual <- EVI %>% group_by(year, month) %>% # agrupamos por año y mes summarise(EVI_mon = mean(EVI_Plantacion, na.rm = T)) # agrupamos usando la media tabla_mensual$dates <- paste(tabla_mensual$year, tabla_mensual$month,"15", sep = "-") %>% as.Date() # construimos vector de fechas para las agrupaciones ``` --- ### Series de tiempo #### Remuestreo temporal <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-12-1.png" width="100%" /> --- ### Series de tiempo #### Remuestreo temporal **Opción 2: usando xts** ``` r library(xts) # la versión para raster es "rts" xts_plantacion <- xts(EVI$EVI_Plantacion, # vector numerico con la variable EVI$Fecha) # vector de fechas EVI_mensual <- apply.monthly(xts_plantacion, FUN = mean) # agregación mensual ``` --- ### Series de tiempo #### Remuestreo temporal <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-14-1.png" width="100%" /> --- ### Series de tiempo #### Test de estacionariedad ``` r library("tseries") ``` **Kwiatkowski-Phillips-Schmidt-Shin (KPSS) test** **H<sub>0</sub>**: La serie de tiempo tiene una tendencia estacionaria. **H<sub>A</sub>**: La serie de tiempo tiene una tendencia no estacionaria. --- ### Series de tiempo #### Test de estacionariedad ``` r kpss.test(EVI$EVI_Plantacion, null = "Trend", lshort = F) ``` ``` ## ## KPSS Test for Trend Stationarity ## ## data: EVI$EVI_Plantacion ## KPSS Trend = 0.30546, Truncation lag parameter = 17, p-value = 0.01 ``` Se rechaza H<sub>0</sub> por lo tanto la serie es no estacionaria. <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-17-1.png" width="100%" /> --- ### Series de tiempo #### Test de estacionariedad ``` r kpss.test(na.omit(EVI$EVI_Nativo), null = "Trend", lshort = F) # Nativo (con NA) ``` ``` ## ## KPSS Test for Trend Stationarity ## ## data: na.omit(EVI$EVI_Nativo) ## KPSS Trend = 0.10944, Truncation lag parameter = 17, p-value = 0.1 ``` No se rechaza H<sub>0</sub> por lo tanto la serie es estacionaria. <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-19-1.png" width="100%" /> --- ### Series de tiempo #### Descomposición de la serie ``` r ts_mensual <- ts(tabla_mensual$EVI_mon, # vector con la variable start = c(2002, 7), # año y mes de inicio de la serie end = c(2023, 10), # año y mes de termino de la serie frequency = 12) # frecuencia de datos al año dec_plant <- decompose(ts_mensual) # descomposición ``` --- ### Series de tiempo <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-21-1.png" width="100%" /> --- ### Series de tiempo: cambios en la varianza y media ``` r library(changepoint) cambio_mv <- cpt.meanvar(EVI$EVI_Plantacion) print(cambio_mv) ``` ``` ## Class 'cpt' : Changepoint Object ## ~~ : S4 class containing 12 slots with names ## cpttype date version data.set method test.stat pen.type pen.value minseglen cpts ncpts.max param.est ## ## Created on : Tue Dec 2 15:29:35 2025 ## ## summary(.) : ## ---------- ## Created Using changepoint version 2.3 ## Changepoint type : Change in mean and variance ## Method of analysis : PELT ## Test Statistic : Normal ## Type of penalty : MBIC with value, 24.78578 ## Minimum Segment Length : 2 ## Maximum no. of cpts : Inf ## Changepoint Locations : 27 96 169 335 353 373 444 ``` --- ### Series de tiempo: cambios en la varianza y media ``` r plot(cambio_mv, type = "l", cpt.col = "blue", xlab = "Tiempo", cpt.width = 4) abline(v = cambio_mv@cpts, col = "red") ``` <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-23-1.png" width="100%" /> --- ### Series de tiempo: cambios en la varianza ``` r cambio_v <- cpt.var(EVI$EVI_Plantacion) print(cambio_v) ``` ``` ## Class 'cpt' : Changepoint Object ## ~~ : S4 class containing 12 slots with names ## cpttype date version data.set method test.stat pen.type pen.value minseglen cpts ncpts.max param.est ## ## Created on : Tue Dec 2 15:29:35 2025 ## ## summary(.) : ## ---------- ## Created Using changepoint version 2.3 ## Changepoint type : Change in variance ## Method of analysis : PELT ## Test Statistic : Normal ## Type of penalty : MBIC with value, 18.58933 ## Minimum Segment Length : 2 ## Maximum no. of cpts : Inf ## Changepoint Locations : 27 169 335 374 ``` --- ### Series de tiempo: cambios en la varianza ``` r plot(cambio_v, type = "l", cpt.col = "blue", xlab = "Tiempo", cpt.width = 4) ``` <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-25-1.png" width="100%" /> --- ### Series de tiempo #### Anomalías respecto a desviaciones de la media (Z-score) usando periodo completo ``` r EVI$Zscore <- scale(EVI$EVI_Plantacion, scale = T) %>% as.numeric() ``` <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-27-1.png" width="100%" /> --- ### Series de tiempo #### Anomalías respecto a desviaciones de la media (Z-score) usando ciclo más estable ``` r EVI$Zscore_2 <- (EVI$EVI_Plantacion - mean(EVI$EVI_Plantacion[169:335]))/sd(EVI$EVI_Plantacion[169:335]) ``` <img src="data:image/png;base64,#DIPGEOPR_03_1_files/figure-html/unnamed-chunk-29-1.png" width="100%" /> --- ### Bibliografía (2012) E. B. Brooks, V. A. Thomas, R. H. Wynne and J. W. Coulston, "Fitting the Multitemporal Curve: A Fourier Series Approach to the Missing Data Problem in Remote Sensing Analysis," in IEEE Transactions on Geoscience and Remote Sensing, vol. 50, no. 9, pp. 3340-3353. doi: 10.1109/TGRS.2012.2183137. (2004) Jin Chen, Per. Jönsson, Masayuki Tamura, Zhihui Gu, Bunkei Matsushita, Lars Eklundh, A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter, Remote Sensing of Environment, Volume 91, Issues 3–4, (2022) Kong, D., McVicar, T. R., Xiao, M., Zhang, Y., Peña-Arancibia, J. L., Filippa, G., Xie, Y., Gu, X. phenofit: An R package for extracting vegetation phenology from time series remote sensing. Methods in Ecology and Evolution, 13, 1508– 1527. https://doi-org.pucv.idm.oclc.org/10.1111/2041-210X.13870 (2015) G. Yang, H. Shen, L. Zhang, Z. He and X. Li, "A Moving Weighted Harmonic Analysis Method for Reconstructing High-Quality SPOT VEGETATION NDVI Time-Series Data," in IEEE Transactions on Geoscience and Remote Sensing, vol. 53, no. 11, pp. 6008-6021. doi: 10.1109/TGRS.2015.2431315. --- class: inverse middle 